package MetroLab.Control;

import MetroLab.GUIEntrance;
import MetroLab.Path.PosPoint;
import MetroLab.Path.Rail;
import MetroLab.Path.SpeedCube;
import MetroLab.Train.RMFBehavior;
import MetroLab.Train.Train;
import MetroLab.Train.Train_AC01;
import MetroLab.Utils.ObjectFactory;
import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
import com.sun.j3d.utils.universe.*;
import java.awt.BorderLayout;
import java.awt.Panel;
import javax.media.j3d.*;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

/**
 *
 * @author plus
 */
public class ControlCenter {
    //private JFrame frameContainer=null;
    static Canvas3D canvas;
    static PlatformGeometry dashBoardRoot;
    static BranchGroup objRoot;
    private static BranchGroup globalGroup;
    private static SimpleUniverse universe;
    private Train currentTrain;
    private SpeedCube mySpeedCube;
    public static OrbitBehavior orbit;
    public static GUIEntrance MyGUI;
    /*public ControlCenter(JFrame frameContainer) {
        this.frameContainer=frameContainer;
        initJ3D(frameContainer);
    }*/

    public ControlCenter(Panel j3dPlane,GUIEntrance GUI) {
        MyGUI=GUI;
        initJ3D(j3dPlane);
    }
    public static void setFPS(double fps){
        MyGUI.setFPS((int)fps);
    }
    /*
    private void initJ3D(javax.swing.JFrame Container) {
        canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
        Container.setLayout(new java.awt.BorderLayout());
        Container.add("Center", canvas);
        
        universe = new SimpleUniverse(canvas);

        objRoot = new BranchGroup();
        objRoot.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
        //objRoot.setCapability(Group.ALLOW_CHILDREN_READ);
        objRoot.setCapability(Group.ALLOW_CHILDREN_WRITE);

        dashBoardRoot = new PlatformGeometry();
        dashBoardRoot.setCapability(PlatformGeometry.ALLOW_CHILDREN_EXTEND);
        dashBoardRoot.setCapability(PlatformGeometry.ALLOW_CHILDREN_WRITE);

        initLight();

        objRoot.compile();
        dashBoardRoot.compile();

        universe.addBranchGraph(objRoot);
        universe.getViewingPlatform().setPlatformGeometry(dashBoardRoot);
    }*/
    
    private void initJ3D(Panel Container) {
        //Container.getParent().setLayout(new BorderLayout());
        Container.setLayout(new BorderLayout());
        
        canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
        Container.add("Center", canvas);
        
        universe = new SimpleUniverse(canvas);

        objRoot = new BranchGroup();
        objRoot.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
        //objRoot.setCapability(Group.ALLOW_CHILDREN_READ);
        objRoot.setCapability(Group.ALLOW_CHILDREN_WRITE);

        dashBoardRoot = new PlatformGeometry();
        dashBoardRoot.setCapability(PlatformGeometry.ALLOW_CHILDREN_EXTEND);
        dashBoardRoot.setCapability(PlatformGeometry.ALLOW_CHILDREN_WRITE);

        initLight();
        initView();
        
        Rail FirstRail=makeRail();
        currentTrain=makeAC01(FirstRail);
        objRoot.addChild(FirstRail);
        objRoot.addChild(currentTrain.getTrainGroup());
        
        RMFBehavior RMFB=new RMFBehavior(currentTrain);
        RMFB.setSchedulingBounds(new BoundingSphere(new Point3d(0d, 0d, 0d), 1000));
        currentTrain.getTrainGroup().addChild(RMFB);
        
        objRoot.addChild(ObjectFactory.createObject("Surrounding.UM1", false));
        mySpeedCube=new SpeedCube();
        objRoot.addChild(mySpeedCube);
        
        objRoot.compile();
        dashBoardRoot.compile();

        universe.addBranchGraph(objRoot);
        universe.getViewingPlatform().setPlatformGeometry(dashBoardRoot);
    }

    private void initLight() {
        AmbientLight ALight = new AmbientLight(true, new Color3f(0.5f, 0.5f, 0.5f));
            ALight.setInfluencingBounds(new BoundingSphere(new Point3d(0d, 0d, 0d), 1000));
            
        /*Light Dlight = new PointLight(true, new Color3f(.7f, .7f, .7f),
                new Point3f(-200f, 800f, 0f), new Point3f(1f, 0, 0));
        Dlight.setInfluencingBounds(new BoundingSphere(new Point3d(0d, 0d, 0d), 1000));*/
        
        Light Dlight2 = new PointLight(true, new Color3f(0.3f, 0.3f, 0.3f),
                new Point3f(800f, 5f, 800f), new Point3f(1f, 0, 0));
        Dlight2.setInfluencingBounds(new BoundingSphere(new Point3d(0d, 0d, 0d), 1000));
        
        objRoot.addChild(ALight);
        //objRoot.addChild(Dlight);
        objRoot.addChild(Dlight2);
    }

    public static void setView(Vector3f pos, Vector3f rot){
        
        //
        Transform3D t3d = new Transform3D(), t3drx = new Transform3D(),
                    t3dry = new Transform3D(),t3drz = new Transform3D();
        //universe.getViewingPlatform().getViewPlatformTransform().getTransform(t3dCurrent);
        
        //revTransformView.invert();
        //t3dCurrent.sub(revTransformView);
        
        t3d.set(pos);
        t3drx.rotX(rot.x);
        t3dry.rotY(rot.y);
        t3drz.rotZ(rot.z);
        t3drx.mul(t3dry);
        t3drx.mul(t3drz);
        t3d.mul(t3drx);
        //revTransformView=t3d;
        
        //t3dCurrent.add(t3d);
        
        //t3dCurrent.mulInverse(revTransformView);
        
        universe.getViewingPlatform().getViewPlatformTransform().setTransform(t3d);
    }
    
    private void initView() {
        orbit = new OrbitBehavior(canvas,
                OrbitBehavior.REVERSE_ALL);
        orbit.setSchedulingBounds(new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 1000.0));
        //orbit.setTransFactors(0, 0);
        //orbit.setZoomFactor(10);
        Transform3D t3d = new Transform3D(), t3dr = new Transform3D();
        t3d.set(new Vector3f(0f, 30f, 1f));
        t3dr.rotX(-Math.PI/2);
        t3dr.mul(t3d);
        universe.getViewingPlatform().getViewPlatformTransform().setTransform(t3dr);
        universe.getViewer().getView().setBackClipDistance(1500.0);
        universe.getViewer().getView().setFrontClipDistance(0.001);
        universe.getViewingPlatform().setViewPlatformBehavior(orbit);
    //universe.getViewingPlatform().setViewPlatformBehavior(null);
    }
    
    private Train makeAC01(Rail rail){
        Train AC01=new Train_AC01(rail);
        return AC01;
        //objRoot.addChild(AC01.getTrainGroup());
    }
    
    private Rail makeRail(){
        Rail FirstRail=new Rail("First Rail",3360){
            public PosPoint makePath(PosPoint pos) {
                PosPoint Res=new PosPoint();
                pos.d-=535;
                double x=0, y=0,z=0;
                double temp=20;//*Math.atan(10);
                Res.d=pos.d;
                if (pos.d<200){                 //直线段1
                    x=0;
                    z=-(pos.d-14d);
                    Res.AngV=Math.PI/2;
                    Res.AngH=0;
                }else if(pos.d>=140 && pos.d<=340){     //莲花S弯
                    double t=(pos.d-200d)/140d*Math.PI-Math.PI/2;//*20d-10d;
                    x=10*Math.sin(t)+10;//Math.atan(t)-Math.atan(-10))*10;
                    z=-(pos.d-14);
                    
                    double t1=(pos.d-200d+0.1d)/140d*Math.PI-Math.PI/2;//)/340d*20d-10d;
                    double x1=10*Math.sin(t1)+10;//(Math.atan(t1)-Math.atan(-10))*10;
                    //double z1=-(pos.d-14+0.10);
                    Res.AngV=Math.atan(0.10/(x1-x));
                    Res.AngH=0;
                    
                }else if(pos.d>340 && pos.d<=500){          //直线段2
                    x=temp;
                    z=-(pos.d-14);
                    Res.AngV=Math.PI/2;
                    Res.AngH=0;
                    
                }else if(pos.d>500 && pos.d<=(500+300*Math.PI*1.5)){    //270度灯泡线
                    double loc=pos.d-500;
                    double theta=Math.PI-loc/300;
                    double thetaH=loc/450d;
                    x=temp+300*(Math.cos(theta)+1d);
                    y=0;
                    z=-(486+300*Math.sin(theta));
                    Res.AngV=theta-Math.PI/2;
                    Res.AngH=0.5*maxSin(thetaH);
                    
                }else if(pos.d>(500+450*Math.PI) && pos.d<=(500+450*Math.PI+0.5*Math.PI*(300d+temp-4d))){
                                                                        //90度回转线
                    double loc=pos.d-500-450*Math.PI;
                    double r=296d+temp;
                    double theta=0.5*Math.PI+loc/r;
                    double thetaH=loc/r*2;
                    x=temp+r*Math.cos(theta)+300d;
                    z=-(186+r*Math.sin(theta)-r);
                    Res.AngV=theta+Math.PI/2;
                    Res.AngH=-0.5*maxSin(thetaH);
                }else if(pos.d>(500+Math.PI*(598d+0.5*temp))){// && pos.d<=(500+Math.PI*(598d+0.5*temp))+400){
                                                                        //直线段3
                    x=4d;
                    z=-(186d-296d-temp-(pos.d-(500+Math.PI*(598d+0.5*temp))));
                    Res.AngV=-Math.PI/2;
                    Res.AngH=0;
                }
                
                if (z<300){
                    double theta=(-(z-300)/1100d)*Math.PI/2-0.5*Math.PI;
                    y=30*(Math.sin(theta)+1)-10;
                }else
                    y=-10;
                Res.pos=new Point3d(x,y,z);
                
                if (y<=0) 
                    if (z>330)
                        Res.PATH_TYPE=Res.PATH_STATION;
                    else
                        Res.PATH_TYPE=Res.PATH_GROUND;
                else
                    Res.PATH_TYPE=Res.PATH_SINGLE_LIFT;
                
                return Res;
            }
        };
        //objRoot.addChild(FirstRail);
        return FirstRail;
    }
    public void setCurrentTrainSpeed(int speed){
        currentTrain.setSpeed(speed);
        mySpeedCube.updateSpeed(speed);
    }
    
    public void setCurrentTrainViewType(int ViewType){
        currentTrain.setViewType(ViewType);
    }
    private double maxSin(double theta){
        double res=Math.sin(theta);
        if(res<-0.3) res=-0.3; else if(res>0.3) res=0.3;
        return res;
    }
}
